home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d (not only polygonal) solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Module to evaluate the binary tree generated by the InptPrsr module. *
- * All the objects are handled the same but the numerical one, which is *
- * moved as a RealType and not as an object (only internally within this *
- * module) as it is frequently used and consumes much less memory this way. *
- * Note this module is par of InptPrsr module and was splited only because *
- * of text file sizes problems... *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include "program.h"
- #include "allocate.h"
- #include "attribut.h"
- #include "convex.h"
- #include "ctrl-brk.h"
- #include "dosintr.h"
- #include "freeform.h"
- #include "geomat3d.h"
- #include "geomvals.h"
- #include "inptprsg.h"
- #include "inptprsl.h"
- #include "objects.h"
- #include "overload.h"
- #include "primitiv.h"
- #include "windows.h"
- #include "iritgrap.h"
-
- InptPrsrEvalErrType
- IPGlblEvalError = IPE_NO_ERR; /* Global used by EvalTree. */
-
- static void LocalPrintTree(ParseTree *Root, int Level, char *Str);
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Returns a string representing the given type. M
- * *
- * PARAMETERS: M
- * Type: Type to get a string representation for. M
- * *
- * RETURN VALUE: M
- * char *: A string describing type Type. M
- * *
- * KEYWORDS: M
- * InptPrsrTypeToStr M
- *****************************************************************************/
- char *InptPrsrTypeToStr(IritExprType Type)
- {
- switch (Type) {
- case POLY_EXPR:
- return "Poly";
- case NUMERIC_EXPR:
- return "Numeric";
- case POINT_EXPR:
- return "Point";
- case VECTOR_EXPR:
- return "Vector";
- case PLANE_EXPR:
- return "Plane";
- case CTLPT_EXPR:
- return "Control Point";
- case MATRIX_EXPR:
- return "Matrix";
- case STRING_EXPR:
- return "String";
- case OLST_EXPR:
- return "List Object";
- case CURVE_EXPR:
- return "Curve";
- case SURFACE_EXPR:
- return "Surface";
- default:
- return "Undefined";
- }
-
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Counts the number of parameters in Root. Parameters are defined as M
- * subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is M
- * represented as [1, [2, [3, 4]]] in the tree supplied to this function and M
- * 4 (number of parameters) is returned. M
- * *
- * PARAMETERS: M
- * Root: To count the number of its parameters. M
- * *
- * RETURN VALUE: M
- * int: Number of parameters encountered. M
- * *
- * KEYWORDS: M
- * InptEvalCountNumParameters M
- *****************************************************************************/
- int InptEvalCountNumParameters(ParseTree *Root)
- {
- int i = 1;
-
- if (Root == NULL)
- return 0;
-
- while (Root -> NodeKind == COMMA) {
- i++;
- Root = Root -> Right;
- }
- return i;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Fetches the i'th paramter out of a tree represent n parameters M
- * (0 <= i < n). See InptEvalCountNumParameters for more description of M
- * structure. M
- * Note it is assumed the tree HAS n parameters and 0<=i<n (No input error). M
- * *
- * PARAMETERS: M
- * Root: To fetch its i'th parameter. M
- * i: The parameter wanted. M
- * n: Total number of parameters in Root. M
- * *
- * RETURN VALUE: M
- * ParseTree *: The requested parameter. M
- * *
- * KEYWORDS: M
- * InptEvalFetchParameter M
- *****************************************************************************/
- ParseTree *InptEvalFetchParameter(ParseTree *Root, int i, int n)
- {
- int j;
-
- for (j = 0; j < i; j++)
- Root = Root -> Right;
-
- if (i == n - 1)
- return Root;
- else
- return Root -> Left;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Fetches the parameters of a function from the parsed tree. M
- * Returns TRUE iff fetching was succesfull. M
- * *
- * PARAMETERS: M
- * Root: Where the parameters should be searched for. M
- * FuncTable: The table's entry of the function we deal with. M
- * NumParams: Number of parameters of function. M
- * Level: Level of recursion. To identify top levels. M
- * Params: Where to put the parameters as ParseTree. M
- * ParamPtrs: And as pointers to RealType/PointType/VectorType etc. M
- * *
- * RETURN VALUE: M
- * int: If everything matches. M
- * *
- * KEYWORDS: M
- * InptEvalFetchParameters M
- *****************************************************************************/
- int InptEvalFetchParameters(ParseTree *Root,
- FuncTableType *FuncTable,
- int NumParams,
- int Level,
- ParseTree *Params[],
- VoidPtr ParamPtrs[])
- {
- int i;
-
- Level++;
- for (i = 0; i < NumParams; i++) {
- if ((Params[i] = InptPrsrEvalTree(InptEvalFetchParameter(Root -> Right,
- i, NumParams),
- Level)) == NULL)
- return i;
-
- if (FuncTable != NULL) {
- if (FuncTable -> ParamObjType[i] == NUMERIC_EXPR)
- ParamPtrs[i] = &Params[i] -> PObj -> U.R;
- else if (FuncTable -> ParamObjType[i] == POINT_EXPR)
- ParamPtrs[i] = Params[i] -> PObj -> U.Pt;
- else if (FuncTable -> ParamObjType[i] == VECTOR_EXPR)
- ParamPtrs[i] = Params[i] -> PObj -> U.Vec;
- else if (FuncTable -> ParamObjType[i] == CTLPT_EXPR)
- ParamPtrs[i] = &Params[i] -> PObj -> U.CtlPt;
- else if (FuncTable -> ParamObjType[i] == PLANE_EXPR)
- ParamPtrs[i] = Params[i] -> PObj -> U.Plane;
- else if (FuncTable -> ParamObjType[i] == STRING_EXPR)
- ParamPtrs[i] = Params[i] -> PObj -> U.Str;
- else
- ParamPtrs[i] = Params[i] -> PObj;
- }
- }
-
- return i;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Tests number of parameters and type of them against what is defined in the M
- * global tables Num/Obj/GenFuncTable. return TRUE if mismatch was detected. M
- * *
- * PARAMETERS: M
- * Root: The function entry node. M
- * *
- * RETURN VALUE: M
- * int: TRUE if a mismatch wasdetected, FALSE of o.k. N
- * *
- * KEYWORDS: M
- * IritEvalFuncParamMismatch M
- *****************************************************************************/
- int IritEvalFuncParamMismatch(ParseTree *Root)
- {
- int FuncOffset, Count,
- i = Root -> NodeKind / 100;
- FuncTableType *FuncTable;
-
- switch (i * 100) {
- case NUM_FUNC: /* Numeric (real returned) functions. */
- FuncOffset = Root -> NodeKind - NUM_FUNC_OFFSET;
- FuncTable = (FuncTableType *) NumFuncTable;
- break;
- case OBJ_FUNC1: /* Object (returned) functions. */
- case OBJ_FUNC2: /* Object (returned) functions. */
- FuncOffset = Root -> NodeKind - OBJ_FUNC_OFFSET;
- FuncTable = (FuncTableType *) ObjFuncTable;
- break;
- case GEN_FUNC:
- FuncOffset = Root -> NodeKind - GEN_FUNC_OFFSET;
- FuncTable = (FuncTableType *) GenFuncTable;
- break;
- default:
- IPGlblEvalError = IE_ERR_FATAL_ERROR;
- UpdateCharError("Undefined function - ", Root -> NodeKind, Root);
- return TRUE;
- }
-
- Count = InptEvalCountNumParameters(Root -> Right);
-
- if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM) {
- for (i = 0; i < Count; i++) {
- IritExprType EType;
-
- /* Special cases - FORLOOP and IF - top level considerations. */
- if ((Root -> NodeKind == FORLOOP && i == 3) ||
- (Root -> NodeKind == IFCOND && i > 0))
- EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
- i, Count), 0);
- else
- EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
- i, Count), 1);
-
- /* Check only for consistency of input. */
- if (EType == ERROR_EXPR)
- return TRUE;
- }
- return FALSE;
- }
- else { /* Number of parameter is well known and is in Count. */
- /* See if number of parameters is ok: */
- if (Count != FuncTable[FuncOffset].NumOfParam) {
- IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
- sprintf(IPGlblCharData, "Func %s - %d expected, %d found",
- FuncTable[FuncOffset].FuncName,
- FuncTable[FuncOffset].NumOfParam,
- Count);
- return TRUE;
- }
-
- /* See if type of parameters are consistent: */
- for (i = 0; i < Count; i++) {
- IritExprType EType;
-
- /* Special cases - FORLOOP and IF - top level considerations. */
- if ((Root -> NodeKind == FORLOOP && i == 3) ||
- (Root -> NodeKind == IFCOND && i > 0))
- EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
- i, Count), 0);
- else
- EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
- i, Count), 1);
-
- if (EType == ERROR_EXPR)
- return TRUE;
- if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
- !(FuncTable[FuncOffset].ParamObjType[i] & EType)) {
- sprintf(IPGlblCharData, "Func %s,%sparameter %d",
- FuncTable[FuncOffset].FuncName,
- IPGlblEvalError == IE_ERR_IP_OBJ_UNDEFINED ?
- " undefined " : " ", i + 1);
- IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
- return TRUE;
- }
- }
- return FALSE;
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Deallocates a parsed tree - release all memory allocated by it. M
- * *
- * PARAMETERS: M
- * Root: Of tree to release. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * InptPrsrFreeTree M
- *****************************************************************************/
- void InptPrsrFreeTree(ParseTree *Root)
- {
- char s[LINE_LEN];
-
- if (!Root)
- return;
-
- if (IS_FUNCTION(Root -> NodeKind)) {
- if (IS_NO_PARAM_FUNC(Root -> NodeKind))
- ExprFree(Root);
- else {
- InptPrsrFreeTree(Root -> Right);
- if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
- IPFreeObject(Root -> PObj); /* Its temp.*/
- ExprFree(Root);
- }
- return;
- }
-
- switch (Root -> NodeKind) {
- case DIV:
- case MINUS:
- case MULT:
- case PLUS:
- case POWER:
- InptPrsrFreeTree(Root -> Right);
- InptPrsrFreeTree(Root -> Left);
- if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
- IPFreeObject(Root -> PObj); /* Its tmp. */
- ExprFree(Root);
- break;
-
- case UNARMINUS:
- case BOOL_NOT:
- InptPrsrFreeTree(Root -> Right);
- if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
- IPFreeObject(Root -> PObj); /* Its tmp. */
- ExprFree(Root);
- break;
-
- case COMMA:
- case COLON:
- case EQUAL:
- case CMP_EQUAL:
- case CMP_NOTEQUAL:
- case CMP_LSEQUAL:
- case CMP_GTEQUAL:
- case CMP_LESS:
- case CMP_GREAT:
- case BOOL_OR:
- case BOOL_AND:
- InptPrsrFreeTree(Root -> Right);
- InptPrsrFreeTree(Root -> Left);
- ExprFree(Root);
- break;
-
- case PARAMETER:
- if (Root -> PObj) {
- /* If object is not part of global variable list - remove it.*/
- if (strlen(Root -> PObj -> Name) == 0)
- IPFreeObject(Root -> PObj);
- else
- Root -> PObj -> Count--;
- }
- ExprFree(Root);
- break;
-
- case NUMBER:
- case STRING:
- if (Root -> PObj)
- IPFreeObject(Root -> PObj);
- ExprFree(Root);
- break;
-
- case TOKENSTART:
- ExprFree(Root);
- break;
-
- case OPENPARA:
- case CLOSPARA:
- ExprFree(Root);
- break;
-
- default:
- /* We might free partially build (by InptPrsr) tree when error */
- /* is detected, and such tree may have nodes with NodeKind>=1000.*/
- if (Root -> NodeKind >= 1000) {
- ExprFree(Root);
- }
- else {
- sprintf(s, "%s (%d).\n",
- "InptPrsrFreeTree: Undefined ParseTree type to free",
- Root -> NodeKind);
- IritFatalError(s);
- }
- break;
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Prints the content of ROOT (using inorder traversal). M
- * If *Str = NULL prints on stderr, else on given string Str. *
- * *
- * PARAMETERS: M
- * Root: Of tree to print. M
- * Str: String to write on the inorder of Root, or stderr if NULL. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * InptPrsrPrintTree M
- *****************************************************************************/
- void InptPrsrPrintTree(ParseTree *Root, char *Str)
- {
- strcpy(IPGlblCharData, ""); /* Make the string empty. */
-
- if (Str == NULL) {
- strcpy(IPGlblCharData, ""); /* Make the string empty. */
- LocalPrintTree(Root, 0, IPGlblCharData); /* Copy to local str. */
- fprintf(stderr, IPGlblCharData); /* and print... */
- }
- else {
- strcpy(Str, ""); /* Make the string empty. */
- LocalPrintTree(Root, 0, Str); /* Dont print to stderr - copy to str. */
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Auxiliary function of InptPrsrPrintTree. *
- * It is assumed Str has at least INPUT_LINE_LEN places to write the *
- * expression. *
- * *
- * PARAMETERS: *
- * Root: Of tree to print. *
- * Level: Of recursion. *
- * Str: String to write on the inorder of Root, or stderr if NULL. *
- * *
- * RETURN VALUE: *
- * void *
- *****************************************************************************/
- static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
- {
- int Len, i,
- CloseFlag = FALSE;
-
- if (!Root)
- return;
- i = Root -> NodeKind / 100;
-
- if ((Len = strlen(Str)) > INPUT_LINE_LEN + 100) /* Prevent overflow. */
- if (Str[Len - 1] == '.')
- return; /* "..." was allready concatenated. */
- else {
- strcat(Str, "...");
- return;
- }
-
- # ifdef DEBUG1
- strcat(Str, "["); /* Usefull to see ALL nestings - no preceedings. */
- # endif /* DEBUG1 */
-
- switch (i * 100) {
- case USER_FUNC:
- switch (Root -> NodeKind) {
- case USERFUNCDEF:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str, "function(");
- break;
- case USERPROCDEF:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str, "procedure(");
- break;
- case USERINSTDEF:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str, Root -> UserFunc -> FuncName);
- strcat(Str, "(");
- break;
- }
- break;
-
- case NUM_FUNC:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str,
- NumFuncTable[Root -> NodeKind - NUM_FUNC_OFFSET].FuncName);
- strcat(Str, "(");
- break;
-
- case OBJ_FUNC1:
- case OBJ_FUNC2:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str,
- ObjFuncTable[Root -> NodeKind - OBJ_FUNC_OFFSET].FuncName);
- strcat(Str, "(");
- break;
-
- case GEN_FUNC:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str,
- GenFuncTable[Root -> NodeKind - GEN_FUNC_OFFSET].FuncName);
- strcat(Str, "(");
- break;
-
- case OPERATORS:
- switch (Root -> NodeKind) {
- case DIV:
- if (Level > 1) {
- strcat(Str, "(");
- CloseFlag = TRUE;
- }
- Level = 1; /* Div Level. */
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "/");
- break;
-
- case MINUS:
- if (Level > 0) {
- strcat(Str, "(");
- CloseFlag = TRUE;
- }
- Level = 0; /* Minus Level. */
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "-");
- break;
-
- case MULT:
- if (Level > 1) {
- strcat(Str, "(");
- CloseFlag = TRUE;
- }
- Level = 1; /* Mul Level. */
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "*");
- break;
-
- case PLUS:
- if (Level > 0) {
- strcat(Str, "(");
- CloseFlag = TRUE;
- }
- Level = 0; /* Plus Level. */
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "+");
- break;
-
- case POWER:
- Level = 2; /* Power Level. */
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "^");
- break;
-
- case UNARMINUS:
- strcat(Str, "(-");
- Level = 0;
- CloseFlag = TRUE;
- break;
-
- case COMMA:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, ",");
- break;
-
- case COLON:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, ":");
- break;
-
- case EQUAL:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "=");
- break;
-
- case CMP_EQUAL:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "==");
- break;
-
- case CMP_NOTEQUAL:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "!=");
- break;
-
- case CMP_LSEQUAL:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "<=");
- break;
-
- case CMP_GTEQUAL:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, ">=");
- break;
-
- case CMP_LESS:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "<");
- break;
-
- case CMP_GREAT:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, ">");
- break;
-
- case BOOL_OR:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "||");
- break;
-
- case BOOL_AND:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "&&");
- break;
-
- case BOOL_NOT:
- LocalPrintTree(Root -> Left, Level, Str);
- strcat(Str, "!");
- break;
-
- case NUMBER:
- sprintf(&Str[strlen(Str)], "%g", Root -> PObj -> U.R);
- break;
-
- case PARAMETER:
- sprintf(&Str[strlen(Str)], "%s", Root -> PObj -> Name);
- break;
-
- case STRING:
- sprintf(&Str[strlen(Str)], "\"%s\"",
- Root -> PObj -> U.Str);
- break;
-
- case OPENPARA:
- strcat(Str, "(");
- break;
-
- case CLOSPARA:
- strcat(Str, ")");
- break;
-
- case TOKENSTART:
- break;
-
- default:
- IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
- }
- break;
-
- default:
- IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
- }
- LocalPrintTree(Root -> Right, Level, Str);
- if (CloseFlag)
- strcat(Str, ")");
-
- # ifdef DEBUG1
- strcat(Str, "]"); /* Usefull to see ALL nestings - no preceedings. */
- # endif /* DEBUG1 */
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Duplicates a parse tree - Generates brand new ParseTree structure but M
- * binds to non-temp variables if they are exists - their Name is not NULL. M
- * This means that updating these objects in the copied tree, will affect M
- * these objects in the original tree. M
- * *
- * PARAMETERS: M
- * Root: To duplicate. M
- * *
- * RETURN VALUE: M
- * ParseTree *: Duplicated parse tree M
- * *
- * KEYWORDS: M
- * InptPrsrCopyTree M
- *****************************************************************************/
- ParseTree *InptPrsrCopyTree(ParseTree *Root)
- {
- ParseTree *NewRoot;
-
- if (Root == NULL)
- return NULL;
-
- NewRoot = ExprMalloc();
-
- if (IS_FUNCTION(Root -> NodeKind)) { /* All the functions. */
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
- if (IS_USER_FUNCTION(Root -> NodeKind))
- NewRoot -> UserFunc = Root -> UserFunc;
- return NewRoot;
- }
-
- switch (Root -> NodeKind) {
- case DIV:
- case MINUS:
- case MULT:
- case PLUS:
- case POWER:
-
- case COMMA:
- case COLON:
- case EQUAL:
- case CMP_EQUAL:
- case CMP_NOTEQUAL:
- case CMP_LSEQUAL:
- case CMP_GTEQUAL:
- case CMP_LESS:
- case CMP_GREAT:
- case BOOL_OR:
- case BOOL_AND:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
- NewRoot -> Left = InptPrsrCopyTree(Root -> Left);
- return NewRoot;
-
- case UNARMINUS:
- case BOOL_NOT:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
- NewRoot -> Left = NULL;
- return NewRoot;
-
- case NUMBER:
- case PARAMETER:
- case STRING:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> PObj = Root -> PObj; /* Point on SAME object. */
- NewRoot -> PObj -> Count++; /* But increase its ref. count. */
- return NewRoot;
-
- case TOKENSTART:
- NewRoot -> NodeKind = Root -> NodeKind;
- return NewRoot;
-
- default:
- IritFatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit");
- }
- return NULL; /* Makes warning silent. */
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Routine to return evaluation error if happen one, zero elsewhere M
- * *
- * PARAMETERS: M
- * Message: Place here a message describing an error, if was one. M
- * *
- * RETURN VALUE: M
- * InptPrsrEvalErrType: Type of evaluation error. M
- * *
- * KEYWORDS: M
- * InptPrsrEvalError M
- *****************************************************************************/
- InptPrsrEvalErrType InptPrsrEvalError(char **Message)
- {
- InptPrsrEvalErrType Temp;
-
- *Message = IPGlblCharData;
- Temp = IPGlblEvalError;
- IPGlblEvalError = IPE_NO_ERR;
-
- return Temp;
- }
-